<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Documentation SimpleTest : le composant de navigation web
scriptable</title>
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
</head>
<body>
<div class="menu_back">
<div class="menu"><a href="index.html">SimpleTest</a> | <a
	href="overview.html">Overview</a> | <a
	href="unit_test_documentation.html">Unit tester</a> | <a
	href="group_test_documentation.html">Group tests</a> | <a
	href="mock_objects_documentation.html">Mock objects</a> | <a
	href="partial_mocks_documentation.html">Partial mocks</a> | <a
	href="reporter_documentation.html">Reporting</a> | <a
	href="expectation_documentation.html">Expectations</a> | <a
	href="web_tester_documentation.html">Web tester</a> | <a
	href="form_testing_documentation.html">Testing forms</a> | <a
	href="authentication_documentation.html">Authentication</a> | <a
	href="browser_documentation.html">Scriptable browser</a></div>
</div>
<h1>Documentation sur le navigateur scriptable</h1>
This page...
<ul>
	<li>Utiliser le <a href="#scripting">navigateur web dans des
	scripts</a></li>
	<li><a href="#deboguer">D&eacute;boguer</a> les erreurs sur les
	pages</li>
	<li><a href="#unit">Tests complexes avec des navigateurs web
	multiples</a></li>
</ul>
<div class="content">

<p>Le composant de navigation web de SimpleTest peut &ecirc;tre
utilis&eacute; non seulement &agrave; l'ext&eacute;rieur de la classe <span
	class="new_code">WebTestCase</span>, mais aussi ind&eacute;pendamment
du framework SimpleTest lui-m&ecirc;me.</p>

<p><a class="target" name="script">
<h2>Le navigateur scriptable</h2>
</a></p>
<p>Vous pouvez utiliser le navigateur web dans des scripts PHP pour
confirmer que des services marchent bien comme il faut ou pour extraire
des informations &agrave; partir de ceux-ci de fa&ccedil;on
r&eacute;guli&egrave;re. Par exemple, voici un petit script pour
extraire le nombre de bogues ouverts dans PHP 5 &agrave; partir du <a
	href="http://www.php.net/">site web PHP</a>...
<pre>
&lt;?php
    require_once('simpletest/browser.php');
    
    $browser = &amp;new SimpleBrowser();
    $browser-&gt;get('http://php.net/');
    $browser-&gt;clickLink('reporting bugs');
    $browser-&gt;clickLink('statistics');
    $browser-&gt;clickLink('PHP 5 bugs only');
    $page = $browser-&gt;getContent();
    preg_match('/status=Open.*?by=Any.*?(\d+)&lt;\/a&gt;/', $page, $matches);
    print $matches[1];
?&gt;
</pre> Bien s&ucirc;r Il y a des m&eacute;thodes plus simple pour
r&eacute;aliser cet exemple en PHP. Par exemple, vous pourriez juste
utiliser la commande PHP <span class="new_code">file()</span> sur ce qui
est ici une page fixe. Cependant, en utilisant des scripts avec le
navigateur web vous vous autorisez l'authentification, la gestion des
cookies, le chargement automatique des fen&ecirc;tres, les redirections,
la transmission de formulaires et la capacit&eacute; d'examiner les
ent&ecirc;tes. De telles m&eacute;thodes sont fragiles dans un site en
constante &eacute;volution et vous voudrez employer une m&eacute;thode
plus directe pour acc&eacute;der aux donn&eacute;es de fa&ccedil;on
permanente, mais pour des t&acirc;ches simples cette technique peut
s'av&eacute;rer une solution tr&egrave;s rapide.
</p>
<p>Toutes les m&eacute;thode de navigation utilis&eacute;es dans <a
	href="web_tester_documentation.html">WebTestCase</a> sont
pr&eacute;sente dans la classe <span class="new_code">SimpleBrowser</span>,
mais les assertions sont remplac&eacute;es par de simples accesseurs.
Voici une liste compl&egrave;te des m&eacute;thodes de navigation de
page &agrave; page...
<table>
	<tbody>
		<tr>
			<td><span class="new_code">addHeader($header)</span></td>
			<td>Ajouter une ent&ecirc;te &agrave; chaque
			t&eacute;l&eacute;chargement</td>
		</tr>
		<tr>
			<td><span class="new_code">useProxy($proxy, $username,
			$password)</span></td>
			<td>Utilise ce proxy &agrave; partir de maintenant</td>
		</tr>
		<tr>
			<td><span class="new_code">head($url, $parameters)</span></td>
			<td>Effectue une requ&ecirc;te HEAD</td>
		</tr>
		<tr>
			<td><span class="new_code">get($url, $parameters)</span></td>
			<td>T&eacute;l&eacute;charge une page avec un GET</td>
		</tr>
		<tr>
			<td><span class="new_code">post($url, $parameters)</span></td>
			<td>T&eacute;l&eacute;charge une page avec un POST</td>
		</tr>
		<tr>
			<td><span class="new_code">clickLink($label)</span></td>
			<td>Suit un lien par son &eacute;tiquette</td>
		</tr>
		<tr>
			<td><span class="new_code">isLink($label)</span></td>
			<td>V&eacute;rifie si un lien avec cette &eacute;tiquette existe</td>
		</tr>
		<tr>
			<td><span class="new_code">clickLinkById($id)</span></td>
			<td>Suit un lien par son attribut d'identification</td>
		</tr>
		<tr>
			<td><span class="new_code">isLinkById($id)</span></td>
			<td>V&eacute;rifie si un lien avec cet attribut d'identification
			existe</td>
		</tr>
		<tr>
			<td><span class="new_code">getUrl()</span></td>
			<td>La page ou la fen&ecirc;tre URL en cours</td>
		</tr>
		<tr>
			<td><span class="new_code">getTitle()</span></td>
			<td>Le titre de la page</td>
		</tr>
		<tr>
			<td><span class="new_code">getContent()</span></td>
			<td>Le page ou la fen&ecirc;tre brute</td>
		</tr>
		<tr>
			<td><span class="new_code">getContentAsText()</span></td>
			<td>Sans code HTML &agrave; l'exception du text "alt"</td>
		</tr>
		<tr>
			<td><span class="new_code">retry()</span></td>
			<td>R&eacute;p&egrave;te la derni&egrave;re requ&ecirc;te</td>
		</tr>
		<tr>
			<td><span class="new_code">back()</span></td>
			<td>Utilise le bouton "pr&eacute;c&eacute;dent" du navigateur</td>
		</tr>
		<tr>
			<td><span class="new_code">forward()</span></td>
			<td>Utilise le bouton "suivant" du navigateur</td>
		</tr>
		<tr>
			<td><span class="new_code">authenticate($username,
			$password)</span></td>
			<td>Retente la page ou la fen&ecirc;tre apr&egrave;s une
			r&eacute;ponse 401</td>
		</tr>
		<tr>
			<td><span class="new_code">restart($date)</span></td>
			<td>Relance le navigateur pour une nouvelle session</td>
		</tr>
		<tr>
			<td><span class="new_code">ageCookies($interval)</span></td>
			<td>Change la date des cookies</td>
		</tr>
		<tr>
			<td><span class="new_code">setCookie($name, $value)</span></td>
			<td>Lance un nouveau cookie</td>
		</tr>
		<tr>
			<td><span class="new_code">getCookieValue($host, $path,
			$name)</span></td>
			<td>Lit le cookie le plus sp&eacute;cifique</td>
		</tr>
		<tr>
			<td><span class="new_code">getCurrentCookieValue($name)</span></td>
			<td>Lit le contenue du cookie en cours</td>
		</tr>
	</tbody>
</table>
Les m&eacute;thode <span class="new_code">SimpleBrowser::useProxy()</span>
et <span class="new_code">SimpleBrowser::addHeader()</span> sont
sp&eacute;ciales. Une fois appel&eacute;es, elles continuent &agrave;
s'appliquer sur les t&eacute;l&eacute;chargements suivants.
</p>
<p>Naviguer dans les formulaires est similaire &agrave; la <a
	href="form_testing_documentation.html">navigation des formulaires
via WebTestCase</a>...
<table>
	<tbody>
		<tr>
			<td><span class="new_code">setField($name, $value)</span></td>
			<td>Modifie tous les champs avec ce nom</td>
		</tr>
		<tr>
			<td><span class="new_code">setFieldById($id, $value)</span></td>
			<td>Modifie tous les champs avec cet identifiant</td>
		</tr>
		<tr>
			<td><span class="new_code">getField($name)</span></td>
			<td>Accesseur de la valeur d'un &eacute;l&eacute;ment de
			formulaire</td>
		</tr>
		<tr>
			<td><span class="new_code">getFieldById($id)</span></td>
			<td>Accesseur de la valeur de l'&eacute;l&eacute;ment de
			formulaire avec cet identifiant</td>
		</tr>
		<tr>
			<td><span class="new_code">clickSubmit($label)</span></td>
			<td>Transmet le formulaire avec l'&eacute;tiquette de son bouton</td>
		</tr>
		<tr>
			<td><span class="new_code">clickSubmitByName($name)</span></td>
			<td>Transmet le formulaire avec l'attribut de son bouton</td>
		</tr>
		<tr>
			<td><span class="new_code">clickSubmitById($id)</span></td>
			<td>Transmet le formulaire avec l'identifiant de son bouton</td>
		</tr>
		<tr>
			<td><span class="new_code">clickImage($label, $x, $y)</span></td>
			<td>Clique sur l'image par son texte alternatif</td>
		</tr>
		<tr>
			<td><span class="new_code">clickImageByName($name, $x,
			$y)</span></td>
			<td>Clique sur l'image par son attribut</td>
		</tr>
		<tr>
			<td><span class="new_code">clickImageById($id, $x, $y)</span></td>
			<td>Clique sur l'image par son identifiant</td>
		</tr>
		<tr>
			<td><span class="new_code">submitFormById($id)</span></td>
			<td>Transmet le formulaire par son identifiant propre</td>
		</tr>
	</tbody>
</table>
Au jourd d'aujourd'hui il n'existe aucune m&eacute;thode pour lister les
formulaires et les champs disponibles : ce sera probablement
ajout&eacute; dans des versions successives de SimpleTest.
</p>
<p>A l'int&eacute;rieur d'une page, les fen&ecirc;tres individuelles
peuvent &ecirc;tre s&eacute;lectionn&eacute;es. Si aucune
s&eacute;lection n'est r&eacute;alis&eacute;e alors toutes les
fen&ecirc;tres sont fusionn&eacute;es ensemble dans une unique et grande
page. Le contenu de la page en cours sera une concat&eacute;nation des
toutes les fen&ecirc;tres dans l'ordre sp&eacute;cifi&eacute; par les
balises "frameset".
<table>
	<tbody>
		<tr>
			<td><span class="new_code">getFrames()</span></td>
			<td>Un d&eacute;chargement de la structure de la fen&ecirc;tre
			courante</td>
		</tr>
		<tr>
			<td><span class="new_code">getFrameFocus()</span></td>
			<td>L'index ou l'&eacute;tiquette de la fen&ecirc;tre en
			courante</td>
		</tr>
		<tr>
			<td><span class="new_code">setFrameFocusByIndex($choice)</span></td>
			<td>S&eacute;lectionne la fen&ecirc;tre num&eacute;rot&eacute;e
			&agrave; partir de 1</td>
		</tr>
		<tr>
			<td><span class="new_code">setFrameFocus($name)</span></td>
			<td>S&eacute;lectionne une fen&ecirc;tre par son
			&eacute;tiquette</td>
		</tr>
		<tr>
			<td><span class="new_code">clearFrameFocus()</span></td>
			<td>Traite toutes les fen&ecirc;tres comme une seule page</td>
		</tr>
	</tbody>
</table>
Lorsqu'on est focalis&eacute; sur une fen&ecirc;tre unique, le contenu
viendra de celle-ci uniquement. Cela comprend les liens &agrave; cliquer
et les formulaires &agrave; transmettre.
</p>

<p><a class="target" name="deboguer">
<h2>O&ugrave; sont les erreurs ?</h2>
</a></p>
<p>Toute cette masse de fonctionnalit&eacute;s est g&eacute;niale
lorsqu'on arrive &agrave; bien t&eacute;l&eacute;charger les pages, mais
ce n'est pas toujours &eacute;vident. Pour aider &agrave;
d&eacute;couvrir les erreurs, le navigateur a aussi des m&eacute;thodes
pour aider au d&eacute;bogage.
<table>
	<tbody>
		<tr>
			<td><span class="new_code">setConnectionTimeout($timeout)</span></td>
			<td>Ferme la socket avec un d&eacute;lai trop long</td>
		</tr>
		<tr>
			<td><span class="new_code">getRequest()</span></td>
			<td>L'ent&ecirc;te de la requ&ecirc;te brute de la page ou de la
			fen&ecirc;tre</td>
		</tr>
		<tr>
			<td><span class="new_code">getHeaders()</span></td>
			<td>L'ent&ecirc;te de r&eacute;ponse de la page ou de la
			fen&ecirc;tre</td>
		</tr>
		<tr>
			<td><span class="new_code">getTransportError()</span></td>
			<td>N'importe quel erreur au niveau de la socket dans le dernier
			t&eacute;l&eacute;chargement</td>
		</tr>
		<tr>
			<td><span class="new_code">getResponseCode()</span></td>
			<td>La r&eacute;ponse HTTP de la page ou de la fen&ecirc;tre</td>
		</tr>
		<tr>
			<td><span class="new_code">getMimeType()</span></td>
			<td>Le type Mime de la page our de la fen&ecirc;tre</td>
		</tr>
		<tr>
			<td><span class="new_code">getAuthentication()</span></td>
			<td>Le type d'authentification dans l'ent&ecirc;te d'une
			provocation 401</td>
		</tr>
		<tr>
			<td><span class="new_code">getRealm()</span></td>
			<td>Le realm d'authentification dans l'ent&ecirc;te d'une
			provocation 401</td>
		</tr>
		<tr>
			<td><span class="new_code">setMaximumRedirects($max)</span></td>
			<td>Nombre de redirections avant que la page ne soit
			charg&eacute;e automatiquement</td>
		</tr>
		<tr>
			<td><span class="new_code">setMaximumNestedFrames($max)</span></td>
			<td>Protection contre des framesets r&eacute;cursifs</td>
		</tr>
		<tr>
			<td><span class="new_code">ignoreFrames()</span></td>
			<td>Neutralise le support des fen&ecirc;tres</td>
		</tr>
		<tr>
			<td><span class="new_code">useFrames()</span></td>
			<td>Autorise le support des fen&ecirc;tres</td>
		</tr>
	</tbody>
</table>
Les m&eacute;thodes <span class="new_code">SimpleBrowser::setConnectionTimeout()</span>,
<span class="new_code">SimpleBrowser::setMaximumRedirects()</span>,<span
	class="new_code">SimpleBrowser::setMaximumNestedFrames()</span>, <span
	class="new_code">SimpleBrowser::ignoreFrames()</span> et <span
	class="new_code">SimpleBrowser::useFrames()</span> continuent &agrave;
s'appliquer sur toutes les requ&ecirc;tes suivantes. Les autres
m&eacute;thodes tiennent compte des fen&ecirc;tres. Cela veut dire que
si une fen&ecirc;tre individuelle ne se charge pas, il suffit de se
diriger vers elle avec <span class="new_code">SimpleBrowser::setFrameFocus()</span>
: ensuite on utilisera <span class="new_code">SimpleBrowser::getRequest()</span>,
etc. pour voir ce qui se passe.
</p>

<p><a class="target" name="unit">
<h2>Tests unitaires complexes avec des navigateurs multiples</h2>
</a></p>
<p>Tout ce qui peut &ecirc;tre fait dans <a
	href="web_tester_documentation.html">WebTestCase</a> peut maintenant
&ecirc;tre fait dans un <a href="unit_tester_documentation.html">UnitTestCase</a>.
Ce qui revient &agrave; dire que nous pouvons librement m&eacute;langer
des tests sur des objets de domaine avec l'interface web...
<pre>
class TestOfRegistration extends UnitTestCase {
    function testNewUserAddedToAuthenticator() {
        $browser = &amp;new SimpleBrowser();
        $browser-&gt;get('http://my-site.com/register.php');
        $browser-&gt;setField('email', 'me@here');
        $browser-&gt;setField('password', 'Secret');
        $browser-&gt;clickSubmit('Register');
        
        $authenticator = &amp;new Authenticator();
        $member = &amp;$authenticator-&gt;findByEmail('me@here');
        $this-&gt;assertEqual($member-&gt;getPassword(), 'Secret');
    }
}
</pre> Bien que &ccedil;a puisse &ecirc;tre utile par convenance temporaire,
je ne suis pas fan de ce genre de test. Ce test s'applique &agrave;
plusieurs couches de l'application, &ccedil;a implique qu'il est plus
que probable qu'il faudra le remanier lorsque le code changera.
</p>
<p>Un cas plus utile d'utilisation directe du navigateur est le
moment o&ugrave; le <span class="new_code">WebTestCase</span> ne peut
plus suivre. Un exemple ? Quand deux navigateurs doivent &ecirc;tre
utilis&eacute;s en m&ecirc;me temps.</p>
<p>Par exemple, supposons que nous voulions interdire des usages
simultan&eacute;s d'un site avec le m&ecirc;me login d'identification.
Ce sc&eacute;nario de test le v&eacute;rifie...
<pre>
class TestOfSecurity extends UnitTestCase {
    function testNoMultipleLoginsFromSameUser() {
        $first = &amp;new SimpleBrowser();
        $first-&gt;get('http://my-site.com/login.php');
        $first-&gt;setField('name', 'Me');
        $first-&gt;setField('password', 'Secret');
        $first-&gt;clickSubmit('Enter');
        $this-&gt;assertEqual($first-&gt;getTitle(), 'Welcome');
        
        $second = &amp;new SimpleBrowser();
        $second-&gt;get('http://my-site.com/login.php');
        $second-&gt;setField('name', 'Me');
        $second-&gt;setField('password', 'Secret');
        $second-&gt;clickSubmit('Enter');
        $this-&gt;assertEqual($second-&gt;getTitle(), 'Access Denied');
    }
}
</pre> Vous pouvez aussi utiliser la classe <span class="new_code">SimpleBrowser</span>
quand vous souhaitez &eacute;crire des sc&eacute;narios de test en
utilisant un autre outil que SimpleTest.
</p>

</div>
References and related information...
<ul>
	<li>La page du projet SimpleTest sur <a
		href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.</li>
	<li>La page de t&eacute;l&eacute;chargement de SimpleTest sur <a
		href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.</li>
	<li><a href="http://simpletest.sourceforge.net/">L'API de
	d&eacute;veloppeur pour SimpleTest</a> donne tous les d&eacute;tails sur
	les classes et les assertions disponibles.</li>
</ul>
<div class="menu_back">
<div class="menu"><a href="index.html">SimpleTest</a> | <a
	href="overview.html">Overview</a> | <a
	href="unit_test_documentation.html">Unit tester</a> | <a
	href="group_test_documentation.html">Group tests</a> | <a
	href="mock_objects_documentation.html">Mock objects</a> | <a
	href="partial_mocks_documentation.html">Partial mocks</a> | <a
	href="reporter_documentation.html">Reporting</a> | <a
	href="expectation_documentation.html">Expectations</a> | <a
	href="web_tester_documentation.html">Web tester</a> | <a
	href="form_testing_documentation.html">Testing forms</a> | <a
	href="authentication_documentation.html">Authentication</a> | <a
	href="browser_documentation.html">Scriptable browser</a></div>
</div>
<div class="copyright">Copyright<br>
Marcus Baker 2006</div>
</body>
</html>
